﻿using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.ESGRatings.BusinessLogic.Validators;
using Xunit;
using Sustainalytics.ESG.Entities;
using Sustainalytics.ESGRatings.Computing.Entities;

namespace Sustainalytics.ESGRatings.BusinessLogic.Tests
{
    [Trait("Category", "Unit")]
    public class CompanyWeightsValidatorTest
    {
        private readonly IValidator<CompanyWeights, CompanyScores> _sut;
        private readonly Guid _companyId = new Guid("3d070700-6668-4ae0-9fa5-505820d2d96e");
        private readonly Guid _matrixGuid = new Guid("290a624d-a1bf-4298-b91d-2456223923d5");
        public CompanyWeightsValidatorTest()
        {
            _sut = new CompanyWeightsValidator();
        }

        [Fact]
        public void IsValid_Company_With_One_IndicatorDefaultScore_Missing_Should_Return_False()
        {
            //Arrange

            var weights = new CompanyWeights()
            {
                CompanyId = _companyId,
                Id = Guid.NewGuid(),
                MatrixId = _matrixGuid,
                Weights = new Dictionary<string, double>
                {
                    {"G.1.1", 0f},
                    {"G.1.5", 1.2f},
                    {"S.1.6", 1.2f},
                    {"S.2.3", 1.2f},
                    {"E.1.3", 1.2f},
                    {"E.2.2", 1.2f},
                    {"E.3.2", 1.2f},
                }
            };

            var indicators = new CompanyScores(
                _companyId, new[]
                {
                    new IndicatorDefaultScore("G.1.1", 50),
                    new IndicatorDefaultScore("G.1.5", 50),
                    new IndicatorDefaultScore("S.1.6", 50),
                    new IndicatorDefaultScore("S.2.3", 50),
                    new IndicatorDefaultScore("E.1.3", 50),
                    new IndicatorDefaultScore("E.2.2", 50),
                });

            //Assert
            var actual = _sut.IsValid(weights, indicators);

            //Act

            Assert.False(actual);

        }


        [Fact]
        public void IsValid_Company_With_No_IndicatorDefaultScores_Should_Return_False()
        {
            //Arrange

            var weights = new CompanyWeights()
            {
                CompanyId = _companyId,
                Id = Guid.NewGuid(),
                MatrixId = _matrixGuid,
                Weights = new Dictionary<string, double>
                {
                    {"G.1.1", 0f},
                    {"G.1.5", 1.2f},
                    {"S.1.6", 1.2f},
                    {"S.2.3", 1.2f},
                    {"E.1.3", 1.2f},
                    {"E.2.2", 1.2f},
                    {"E.3.2", 1.2f},
                }
            };

            var indicators = new CompanyScores(
                _companyId, Enumerable.Empty<IndicatorDefaultScore>()
                );

            //Assert
            var actual = _sut.IsValid(weights, indicators);

            //Act

            Assert.False(actual);

        }

        [Fact]
        public void IsValid_Company_With_IndicatorDefaultScore_and_Weights_Match_Should_Return_True()
        {
            //Arrange

            var weights = new CompanyWeights()
            {
                CompanyId = _companyId,
                Id = Guid.NewGuid(),
                MatrixId = _matrixGuid,
                Weights = new Dictionary<string, double>
                {
                    {"G.1.1", 0f},
                    {"G.1.5", 1.2f},
                    {"S.1.6", 1.2f},
                    {"S.2.3", 1.2f},
                    {"E.1.3", 1.2f},
                    {"E.2.2", 1.2f},
                    {"E.3.2", 1.2f},
                }
            };

            var indicators = new CompanyScores(
                _companyId, new[]
                {
                    new IndicatorDefaultScore("G.1.1", 50),
                    new IndicatorDefaultScore("G.1.5", 50),
                    new IndicatorDefaultScore("S.1.6", 50),
                    new IndicatorDefaultScore("S.2.3", 50),
                    new IndicatorDefaultScore("E.1.3", 50),
                    new IndicatorDefaultScore("E.2.2", 50),
                    new IndicatorDefaultScore("E.3.2", 50),
                });

            //Assert
            var actual = _sut.IsValid(weights, indicators);

            //Act

            Assert.True(actual);

        }


        [Fact]
        public void IsValid_Company_With_Fewer_Weights_Set_Than_IndicatorDefaultScores_Should_Return_True()
        {
            //Arrange

            var weights = new CompanyWeights()
            {
                CompanyId = _companyId,
                Id = Guid.NewGuid(),
                MatrixId = _matrixGuid,
                Weights = new Dictionary<string, double>
                {
                    {"G.1.1", 0f},
                    {"G.1.5", 1.2f},
                    {"S.1.6", 1.2f},
                    {"S.2.3", 1.2f},
                    {"E.1.3", 1.2f},
                    {"E.2.2", 1.2f},
                }
            };

            var indicators = new CompanyScores(
                _companyId, new[]
                {
                    new IndicatorDefaultScore("G.1.1", 50),
                    new IndicatorDefaultScore("G.1.5", 50),
                    new IndicatorDefaultScore("S.1.6", 50),
                    new IndicatorDefaultScore("S.2.3", 50),
                    new IndicatorDefaultScore("E.1.3", 50),
                    new IndicatorDefaultScore("E.2.2", 50),
                    new IndicatorDefaultScore("E.3.2", 50),
                });

            //Act
            var actual = _sut.IsValid(weights, indicators);

            //Assert

            Assert.True(actual);

        }


        [Fact]
        public void IsValid_Null_CompanyWeights_Throws_ArgumentNullException()
        {
            //Arrange


            var indicators = new CompanyScores(
                _companyId, new[]
                {
                    new IndicatorDefaultScore("G.1.1", 50),
                    new IndicatorDefaultScore("G.1.5", 50),
                    new IndicatorDefaultScore("S.1.6", 50),
                    new IndicatorDefaultScore("S.2.3", 50),
                    new IndicatorDefaultScore("E.1.3", 50),
                    new IndicatorDefaultScore("E.2.2", 50),
                    new IndicatorDefaultScore("E.3.2", 50),
                });

            //Act & Assert




            Assert.Throws<ArgumentNullException>(() => _sut.IsValid(null, indicators));




        }


    }
}
